package com.tedu.API.io;

import org.junit.Test;

import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * 标准的IO流---目的: 数据传输   输出文本、图片
 * java定义一套标准流--->数据传输--->创建流: 直接创建某个流对象
 * 标准流规则①: 方向划分  输入流和输出流
 *              输入流: 读入--->文件--->相对于程序--->文件往程序走
 *              InputStream(抽象类: 定义所有读的写法) 【学习: 子实现类】
 *              输出流: 写出--->文件--->相对与程序--->程序写出
 *              OutputStream(抽象类: 定义所有写的方法) 【学习: 子实现类】
 *         ②: 功能划分
 *     -->   低级流【又称节点流】: 是建立在程序与数据源之间的"管道"
 *                  功能: 负责搬运的数据流, 输入流于输出流都有自己的低级流
 *                  特点: 一个字节一个字节读或者写的方法
 *         FileOutputStream    低级流继承InputStream-->文件输出流:实现 写 功能
 *         FileInputStream     低级流继承OutputStream--->文件输入流:实现 读 功能
 *         高级流【又称处理流】: 不能直接创建对象, 不能独立存在
 *                 功能: 处理低级流以及其他高级流的流
 *                 特点: 搬运数据时，实现具体功能: 效率提高流
 *
 * ----------总结: 输入流和输出流，具备功能: 低级流与高级流，
 *     实际使用: 明确使用具体流，每个流都有自己提供的功能
 */
public class IOAPI {
    /**
     * ①输入流
     * 标准流  一、方向划分
     * ②输出流
     * <p>
     * (1)文件输入流
     * 二、功能:   ①低级流:     (2)文件输出流: FileOutputStream
     * ②高级流:
     * 需求: 写出一个文件  fos.txt
     *
     * FileOutputStream   构造器使用
     * new FileOutputStream("路径+文件全称")
     * new FileOutputStream("路径+文件全称",boolean append)
     * 写出文件的同时实现追加效果, 第二个参数: true  追加
     * false 默认不追加
     * new FileOutputStream(File file,boolean append)  过于多余
     * 写出文件，采用File传入路径+全称
     */
    @Test
    public void testFOS() throws IOException {
        /* RandomAccessFile raf=
                 new RandomAccessFile("fos.txt","rw");*/
        //低级流----文件输出流对象---从程序写出"文件: 数据"
        FileOutputStream fos = new FileOutputStream("fos.txt", true);
        //需求: fos.txt   增加一行文本  每次运行实现追加效果
        String say = "众生皆病";
        String say1 = "我亦如此";
        //字符串由字节数组构成---数组的功能---getBytes()转换为字节数组
        //输出流---写功能: write(byte[] b)  写出字节数组
        fos.write(say.getBytes());
        fos.write(say1.getBytes());
        //必须关闭流---目的: 节省内存开销
        fos.close();
    }

    /**
     * 文件输入流: 读入操作
     * FileInputStream  文件输入流
     * read() 返回一个读取一个字节---效率低
     * read(字节数组byte[] b)  返回一个"指定字节数组:空间大小"的读取---效率高
     * 需求: 读入fos.txt文件内容
     */
    @Test
    public void testFIS() throws IOException {
        //创建文件输入流---读入: fos.txt
        FileInputStream fis=new FileInputStream("fos.txt");
        //读入效率高: 创建字节数组---指定空间为: 10KB
        byte[] data=new byte[1024*10];
        //读入操作: read(字节数组)  |  以10KB读入数据
        int len=fis.read(data);
        //写出: 文本----字符串---针对流操作，提供特殊的构造器
        //                     文件按照"指定字节数组空间"写入程序中
        //                     从0开始写入程序，写入到-1结束
        //                     len: 十进制转换为二进制，写入，不等于-1，一值写入
        // 一次性将给定数据按照字节数组指定空间大小，写出成字符串
        String str=new String(data,0,len);
        System.out.println("打印fos.txt文件: "+str);
    }

    /**
     * 需求: 利用标准流实现视频复制粘贴
     */
    @Test
    public void testCV() throws IOException {
        //1.从"复制视频.mp4"  复制操作---读入
        FileInputStream xcv=new FileInputStream("复制视频.mp4");
        //2.创建新文件"新文件.mp4" 粘贴操作---写出
        FileOutputStream zxc=new FileOutputStream("新文件.mp4");
        //3.保存每次读取的数据【字节量---int类型】
        int len=-1;
        //4.一直从"复制文件.mp4" 进行读入操作，不等于-1   一直读
        // len=xcv.read();
        long start=System.currentTimeMillis();
        while( (len=xcv.read())!=-1  ){  //true
            //4.1同时 写出"新文件.mp4"
            zxc.write(len);
        }
        long end=System.currentTimeMillis();
        System.out.println("花费时间:  "+(end-start)/1000+"秒");
        //5.关闭流         ------测: 效率低---正常播放
        xcv.close();   zxc.close();  //低级流都需要关
    }

    /**
     * 需求: 利用标准流实现视频复制粘贴---效率低
     *                               效率高---> 空间指定为: 自定 100KB
     *
     * 【高级流】:
     * BufferedInputStream  缓冲输入流-提升效率-缓冲区:字节数组【长度不确定，按照文件大小进行合理分配】
     *BufferedOutputStream  缓冲输出流-提升效率-缓冲区:字节数组【长度不确定，按照文件大小进行合理分配】
     *   高级流的使用方式: ①处理低级流，套在低级流上
     *                   写法:new 高级流(传入低级流引用)
     *                  ②直接使用高级流的方法
     *                  ③高级流不能直接创建【不能独立存在】
     */
    @Test
    public void testCVS() throws IOException {
        //1.输入流:
        //1.创建低级流: 读入"复制视频.mp4"
        FileInputStream fis=new FileInputStream("复制视频.mp4");
        //1.创建一个高级流: 套在低级流上【自带缓冲区: 字节数组】
        BufferedInputStream bis=new BufferedInputStream(fis);

        //2.输出流:
        //2.创建低级流: 写出"高效视频.mp4"
        FileOutputStream fos=new FileOutputStream("高效视频.mp4");
        //2.创建高级流: 套在低级流上【自带缓冲区: 字节数组】
        BufferedOutputStream bos=new BufferedOutputStream(fos);

        //3.保存数据
        int len=-1;
        //4.高级流--低级流方法一致---read() 读取内嵌缓冲区【字节数组】
        // 高级流---低级流方法一致---write() 写出内嵌的缓冲区【字节数组】
        //一直从"复制视频.mp4"读取数据，不等于-1，一直读
        // (bis.read())!=-1方法
        long start=System.currentTimeMillis();
        while ((len=bis.read())!=-1){
            bos.write(len);
        }
        long end=System.currentTimeMillis();
        System.out.println("缓冲流【自带缓冲区】:  "+(end-start)+"毫秒");
        //关闭流---高级流与低级流: 都关闭--->高级流可以间接性关闭低级流-->关闭高级流
        //                              从高级流开始关闭，再关闭低级流
        bis.close();  //高级流--缓冲输入流
        bos.close();  //高级流--缓冲输出流
    }

    /**
     * 高级流---缓冲流【内嵌缓冲区】
     * BufferOutputStream  缓冲输出流
     *
     * 需求: 通过缓冲输出流实现从程序写出文件: bos.txt,写出内容
     */
    @Test
    public void testBOS() throws IOException {
        //1.创建低级流--->bos.txt文件
        FileOutputStream fos=new FileOutputStream("box.txt");
        //2.创建高级流--->缓冲区: 字节数组---合理
        BufferedOutputStream bos=new BufferedOutputStream(fos);
        //3.写出文件的文本内容
        String str="只道是，流水桃花最难辨，消得几回潮落又潮生  ";
        String say="坛起荤香飘四邻，你也是闻到我的香气越墙而来的吗?";
        //4.写出到bos.txt 文件中:  字符串转成字节数组---写出
        bos.write(str.getBytes());
        bos.write(say.getBytes());
        //5.将缓冲区数据一次性进行写出  flush()  【立即写出】
        //bos.flush();
        //举例: A    你好  你认识我吗    干啥呢
        //     B     你好  你认识我吗    干啥呢
        // A说的全部显示到B，flush()负责把A的话送到B
        bos.close();  //关闭流---一定会把缓冲区的数据全部写出
    }

    /**
     * 标准IO---成对【低级流+高级流】结合异常---数据传输---成功【异常需要捕获】
     * 重构 testBOS() 单元测试
     */
    @Test
    public void testBOSIO(){
        //1.置空流---提升所有流作用域: 适用范围
        FileOutputStream fos=null;  //低级流置空:搬运数据
        BufferedOutputStream bos=null; //高级流置空: 缓冲输出流
        //2.捕获流异常并且作出处理
        try {
            fos=new FileOutputStream("bos.txt");  //低级流
            bos=new BufferedOutputStream(fos);  //高级流: 缓冲区: 字节数组
            bos.write("你是唯一的收官之子".getBytes());
            bos.flush();
        }catch (FileNotFoundException e){  //IO流 “小” 异常
            e.printStackTrace();
        } catch (IOException e) {  //IO流 "中" 异常: 小异常父类
            e.printStackTrace();
        }catch (Exception e){  //  "大" 异常  Exception
            e.printStackTrace();
        } finally { //一定执行代码块
            //3.关闭流---高级流---释放资源
            //判断高级流是否为空: 高级流一定不为空-->关闭
            if (bos!=null)
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }


    /**
     * 重构FOS 单元测试
     */
    @Test
    public void testFOSIO(){
        FileOutputStream fos=null;
        try {
            fos=new FileOutputStream("fos.txt",true);
        } catch (FileNotFoundException e) {  //小异常
            e.printStackTrace();
        } finally {
        }
        String say="众生皆病";
        String say1="我亦如此";
        try {
            fos.write(say.getBytes());
        } catch (IOException e) {  //中异常
            e.printStackTrace();
        } finally {
        }
        try {
            fos.write(say1.getBytes());
        } catch (IOException e) {  //中异常
            e.printStackTrace();
        } finally {
            if(fos!=null)
           try {
               fos.close();
           }catch (IOException e) {
               e.printStackTrace();
           }
        }
    }


    /**
     * 重构 FIS 单元测试
     */
    @Test
    public void testFISIO(){
        FileOutputStream fis=null;
        try {
            fis=new FileOutputStream("fox.txt");
        } catch (FileNotFoundException e) {  //小异常
            e.printStackTrace();
        } finally {
            if(fis!=null)
                try{
                    fis.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
        }
        System.out.println("打印fos.txt文件: ");
    }


    /**
     * 重构 CV 单元测试
     */
    @Test
    public void testCVIO(){
        FileOutputStream xcv=null;
        FileOutputStream zxc=null;
        try {
            xcv=new FileOutputStream("复制视频.mp4");
            zxc=new FileOutputStream("新文件.mp4");
        }catch (FileNotFoundException e){ //小异常
            e.printStackTrace();
        }
        finally {
            if(xcv!=null)
              try{
                  xcv.close();
                  zxc.close();
              } catch (IOException e){
                  e.printStackTrace();
              }
        }
    }


    /**
     * 重构 CVS 单元测试
     */
    @Test
    public void testCVSIO(){
        FileOutputStream fis=null;
        BufferedOutputStream bis=null;
        try {
            fis=new FileOutputStream("复制视频.mp4");
            bis=new BufferedOutputStream(fis);
        } catch (FileNotFoundException e) {  //小异常
            e.printStackTrace();
        } finally {
            if(bis!=null)
                try {
                    fis.close();
                    bis.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
        }
        FileOutputStream fos=null;
        BufferedOutputStream bos=null;
        try {
            fos=new FileOutputStream("高效视频.mp4");
            bos=new BufferedOutputStream(fos);
        } catch (FileNotFoundException e) {  //小异常
            e.printStackTrace();
        } finally {
            if(bos!=null)
                try{
                    fos.close();
                    bos.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
        }
    }
}
